from typing import TYPE_CHECKING, Dict, List
if TYPE_CHECKING:
    from .Pos import PosSet, Pos
    from .Chess import ChessBase
    from .Game import Game
from .History import KillEvent, MoveEvent, SkillEvent
import json


class Board:
    board: "Dict[Pos,ChessBase]" = {}
    score: "List[int]" = [0, 0, 0, 0]
    game: "Game" = None

    def to_json(self):
        tmp = []
        for i in self.board:
            tmp.append(json.loads(self.board[i].to_json()))
        return json.dumps(tmp)

    def __init__(self, game: "Game|None" = None):
        self.game = game

    def has_chess(self, x: "Pos") -> bool:
        return self.board.__contains__(x)

    def get_chess(self, x: "Pos") -> "ChessBase":
        return self.board.get(x, None)

    def can_kill(self, who: "ChessBase", x: "Pos") -> bool:
        if self.has_chess(x) == False:
            return True  # 如果没有棋子返回 true
        chess = self.get_chess(x)
        if chess.player == who.player:
            return False  # 不可以自己杀自己棋子
        return chess.death.can_be_killed(who)

    # TODO in pawn-pawn chess,there is no king
    def kill_chess(self, player: int, killer: "ChessBase", x: "Pos") -> None | str:
        if x.valid() == False:
            return None
        if self.has_chess(x) == False:
            return None
        chess = self.get_chess(x)
        self.score[player] = self.score[player]+chess.point
        self.board.pop(x)
        chess.death.on_death(killer)
        return chess.type

    def try_move(self, player: int, x: "Pos", target: "Pos") -> bool:
        if target.valid() == False:
            return False
        if x.valid() == False:
            return False
        if self.has_chess(x) == False:
            return False
        chess = self.get_chess(x)
        if chess.move.can_move_to(player, target) == False:
            return False
        res = self.kill_chess(player, chess, target)
        self.board.pop(x)
        self.board[target] = chess
        if self.game is not None:
            self.game.commit_history(
                MoveEvent(player, chess.type, chess.pos, target))
            if res is not None:
                self.game.commit_history(
                    KillEvent(player, chess.type, chess.pos, res, target))
        return True

    def try_skill(self, player: int, pos: "Pos", **kwargs):
        if pos.valid() == False:
            return False
        if self.has_chess(pos) == False:
            return False
        chess = self.get_chess(pos)
        if chess.player != player:
            return False
        if chess.skill.can_use_skill(**kwargs) == False:
            return False
        if self.game is not None:
            self.game.commit_history(SkillEvent(
                player, chess.type, pos, chess.skill.describing_str(**kwargs)))
        res = chess.skill.trigger_skill(**kwargs)
        return True
